Balloon Fight Level Data & Hacking Information (v1.1)
Document written by: Quick Curly
August 5, 2015
-------------------------------------------------------------------------------
Table of Contents

 1. Intentions & Purposes
 2. Hacking Tools/What You Will Need
 3. Balloon Fight ROM Information
 4. RAM Addresses, PPU Addresses, and ROM Addresses
5a. NROM-128 to NROM-256 Conversion/Expansion - Introduction
5b. NROM-128 to NROM-256 Conversion/Expansion - The Tutorial
 6. Balloon Fight RAM & ROM Addresses
 7. Level Header Format
 8. Platform Collision/Detection
 9. Graphics
10. Enemy Data
11. Object Data
12. Palette Data
13. Fish
14. Tips - Building Your Levels From Scratch
15. Examples of Custom Code
 a. Disable Game Demo
 b. Disable Fish
 c. Custom Palette Code
16. Acknowledgements, Credits & Thank You Section
17. Other Potential Areas of Consideration/What's to Come
18. Change Log
19. Contacts
-------------------------------------------------------------------------------
 1. Intentions & Purposes

 This document is intended to cover a range of ROM hacking related topics and
aspects specifically for the NES game, Balloon Fight.

 This document attempts to be as thorough and detailed as possible, much like
most tutorials and explanations that I write. Please expect to take some time
while reading through everything. The basic instructions and directions are
there, but minor details are explored whenever and wherever possible. I've
always been more of an "answer the questions before they're asked" kind of guy.
This is especially critical when writing a document. Any questions that you may
potentially have after everything is covered will hopefully simply cover NES-
specific details that can be answered through additional searching elsewhere.

 I originally began looking at the Balloon Fight ROM back in 2011, randomly and
out of interest. I came back to working on a more accurate and thorough
documentation years later around the end of June and beginning of July in 2015,
following the release of my Quick Bros. 2 Hack Pack.

 I grew up with this game, along with many others, and enjoyed playing it on my
own and also with other family members. Interest in how the game worked and if
it was possible to successfully make more than just a graphic hack was an
occasional thought ever since I came to discover ROM hacking as a whole in
2007; however, I didn't always have the knowledge and skill set to be able to
pursue such an endeavor. Though, over time, with each completed project, I
learned more, and now have more experience with being able to search for the
unknown and succeed in figuring things out.

 I enjoy being able to contribute and give back to the ROM hacking community
that has helped me develop my own abilities to achieve what I always hoped was
possible in bringing new life and personal customizations to some of my
favourite childhood games. I wanted to provide the valuable information and
experience that I have learned to others in hopes that it can lead to their own
dreams coming true as well, which in turn gifts players and hackers alike more
fresh takes on favourite classics, and hopefully encourage them to continue the
cycle and progression for us all by sharing what they learn to others.

 While it's extremely helpful and convenient for the hacking process to be
simplified by the efforts of programmers who commit time and effort to write
highly valuable utilities designed for a specific game, it's difficult when
there isn't a program like a level editor for a game that we could be
interested in modifying. However, never say never! Thanks to special emulators
and debuggers like FCEUX/FCEUXD, which are also utilities that thankfully
already exist, we have the resources we need to potentially develop first-time
projects.

 This document also aims to provide some insight and hacking techniques for
approaching and attempting to find data, code, and other functions of a game
that is barely hacked, or has not been hacked at all yet.

 The documented data of Balloon Fight found in this document is hopefully
accurate and complete enough for anyone who might have knowledge, time, and
personal interest to invest in writing some form of level editor, if they so
choose. They could call it "Balloon Trip", or "BTO: Balloon Trippin' Out", or
something.

 Overall, hopefully the information and step-by-step tutorials in this document
will help provide new hopeful hackers some beginning knowledge to build from,
and an idea of what to expect when having to problem solve on their own,
especially for less commonly known games and projects of interest.

 For any information that can be added or clarified, please contact me about
any inquiries. Please refer to the "Contacts" section for methods of contact.
Any information that is contributed to this document will be properly credited
in the "Acknowledgements, Credits & Thank You Section". Thank you.
-------------------------------------------------------------------------------
 2. Hacking Tools/What You Will Need

 Depending on exactly what you want to modify, you may not require all of the
following downloads and programs, but they are used in the tutorial in section
5b.

- Balloon Fight NES ROM by Nintendo
- FCEUXD emulator (v1.0a) by bbitmaster
- HxD hex editor by Mal Hrz
- WindHex32 hex editor (v.2005.4.20) by Bongo`


 Additional items you may choose to use on your own:

- beat (v01) by byuu
- Lunar IPS (v1.02) by FuSoYa
- Tile Layer Pro graphics editor (v1.1) by SnowBro
- Tile Layer Pro 1.1 Unofficial Bug Fix Patch (v1.1) by Kejardon
-------------------------------------------------------------------------------
 3. Balloon Fight ROM Information

 The Balloon Fight ROM has the following common name and checksums, found with
the HxD hex editor.

 After downloading the HxD hex editor:

- Open your ROM (Google for that too) in the program.
- Under the Analysis menu, select Checksums.
- Under "Available algorithms", highlight all the checksums that you want to
  display. Hold down the left CTRL key to make single selections, or hold down
  the right SHIFT key to select a range.
- Select OK.

Balloon Fight (U) [!].nes

Checksum-16: 0672
Checksum-32: 00230672
Checksum-64: 0000000000230672
CRC-16: 59E6
CRC-32: CB8FD7B2
SHA-1: F5E4CD9F287A8233EEE35AD1881B2770D9F2C453
SHA-256: 9710F31E7EE204A69AAAAFB6AF340EFEC89657A245C8D402DEE95DAEA4F8A49F
MD-5: 6E125395CA4F18ADDB8CE6C9152DEA85

 The reasons you want to check for these checksums are:

- To make sure that the ROM that you have is the exact same ROM that is being
  used as an example in this tutorial.
- When people play your hack, they need to know which original ROM to apply
  your patch to (because it needs to be the same).
- If your ROM is not the same as the one in this tutorial, the RAM addresses,
  ROM addresses, and other data provided could be different.

 It would not be impossible to modify other ROMs of this game, but the
information in this tutorial is specific for the version mentioned above. The
information could potentially be applied to other versions, though.
-------------------------------------------------------------------------------
 4. RAM Addresses, PPU Addresses, and ROM Addresses

 In a NES ROM, there are RAM addresses, PPU addresses, and ROM addresses.

 An address is basically a location. Another term commonly used is "offset".

 RAM stands for Random Access Memory.
 This is basically the part of a game that is "what's going on". All of the
many things happening at any given moment - a player running, a level loaded, a
demo sequence running - are all controlled by the variables in this memory.
 RAM addresses are normally denoted, or displayed, by inserting a "$" symbol in
front of a hexadecimal number. For example, $03A5, or $7CD0.
 The space is limited to a range of $0000 to $FFFF.

 PPU stands for Picture Processing Unit.
 This is basically the part of a game that you see. What is on the screen at
any given moment, and the colours that are in a palette that are used to colour
in images and sprites on the screen, is all controlled by the data loaded into
this memory.
 PPU addresses are normally denoted by inserting a "$" symbol in front of a
hexadecimal number. For example, $20FA, or $3F00.
 To distinguish between RAM addresses and PPU addresses, it's best to declare
which you mean when you provide the number of an address location. For example,
RAM address $03A5, or PPU address $20FA.
 The space is limited to a range of $0000 to $3FFF.

 ROM stands for Read Only Memory.
 This is basically everything that makes up a game, but it cannot be modified
during the ordinary course of operation. This includes the constant data, code,
and graphics.
 There are 2 main sections of the ROM: PRG-ROM and CHR-ROM. There is also a
header at the very beginning of the ROM file, consisting of 16 bytes. We'll
look at that more in a minute, though.
 PRG-ROM means Programmable ROM. This includes data and code that applies the
functions and core of the game to get it to run and do stuff.
 CHR-ROM means Character ROM. Essentially, this area is made up of graphics
used in the game. This includes object images and sprites.
 ROM addresses are normally denoted by inserting a number "0" and small letter
"x" in front of a hexadecimal number. For example, 0x006B, or 0x1FB92.

 For RAM and PPU:

 [$] [20FA]
  |   |
  |   This tells you the address location
  |
  This tells you what kind of address

 For ROM:

 [0x] [1FB92]
  |    |
  |    This tells you the address location
  |
  This tells you what kind of address

 Each address consists of a value. The addresses and their values are viewable
when you open a ROM file in any hex editor program.


 The NES header basically tells an emulator and other programs how everything
is set up. This includes:

- The ROM being a ".nes" file.
- The number of PRG-ROM pages in 16 KB sizes.
- The number of CHR-ROM pages in 8 KB sizes.
- The mapper that the ROM uses, if any.
- Other various functions not covered or applicable to Balloon Fight
  specifically.


 The layout and ranges for the original, unmodified ROM are as follows:

0x0000-0x000F (0x0010): NES ROM Header
0x0010-0x400F (0x4000): PRG-ROM
0x4010-0x600F (0x2000): CHR-ROM

 The layout and ranges for an expanded ROM are as follows:

0x0000-0x000F (0x0010): NES ROM Header
0x0010-0x800F (0x8000): PRG-ROM
0x8010-0xA00F (0x2000): CHR-ROM


 A range is a number of consecutively selected offsets. For example, the range
of 0x0000 to 0x000F, the NES ROM header in this case, starts with byte 0x0000,
ends with 0x000F, and the length of this range is 0x0010 bytes selected in hex.
-------------------------------------------------------------------------------
5a. NROM-128 to NROM-256 Conversion/Expansion - Introduction

 Balloon Fight uses iNES Mapper 0, assigned to NROM. Originally, it has
1 PRG-ROM page and 1 CHR-ROM page.

 It is capable of 1 PRG-ROM page (16 KB in size) for NROM-128, or 2 PRG-ROM
pages (32 KB in size) for NROM-256.

 When the game loads, the PRG-ROM is loaded into RAM. Depending on whether the
PRG-ROM is 1 page or 2 pages, the ranges for RAM are laid out as follows:

Balloon Fight - 24.0 KB (25 KB) - RAM (NROM-128):
$8000-$9FFF: 0x0010-0x200F
$A000-$BFFF: 0x2010-0x400F
$C000-$DFFF: 0x0010-0x200F
$E000-$FFFF: 0x2010-0x400F

Balloon Fight - 40.0 KB (41 KB) - RAM (NROM-256):
$8000-$9FFF: 0x0010-0x200F
$A000-$BFFF: 0x2010-0x400F
$C000-$DFFF: 0x4010-0x600F
$E000-$FFFF: 0x6010-0x800F

 To view in RAM which ROM bank is loaded within each region at any given point
in time, you can open your ROM in the FCEUXD emulator, pause the game from the
main window with F2 (in order to freeze RAM in time so that, with larger games
that swap banks on the fly, you can view exactly what is in RAM at that precise
moment), and then hover the cursor over the vertical bar along the left side.

 As you can see, the $8000-$9FFF and $C000-$DFFF ranges match, as do the
$A000-$BFFF and $E000-$FFFF ranges with NROM-128. Adding a second NROM-capable
PRG-ROM page can effectively expand one's free space with a no-mapper game.

 Balloon Fight is pretty much full as it is with considerably few free, unused
bytes. Expanding the ROM can potentially allow much more free space for more
detailed levels, additional enemies, and coding capabilities for the very
creative (for example, additional palettes or more levels with appropriate
custom code, among other things).

 Balloon Fight's code all functions within the $C000-$FFFF range. Even though
$8000-$BFFF is mapped the same between both set-ups, it is not even actually
used by the original game.

 There are a few factors to consider when deciding whether or not to follow
through with such a change, and if it is truly necessary. For example, NROM-128
cartridge boards only support 16 KB games, but NROM-256 cartridge boards can
support both 16 KB and 32 KB games.

 Another factor to consider is that the patch size for your published hack will
be larger. This really doesn't pose as a disadvantage of any sort, but there
generally isn't a point in having a larger ROM file size unless you can
actually make use of the additional free space.

 To prevent original game data and code from being included in your patch file,
if you choose to expand your ROM size, it is recommended that you use the BPS
patch format instead of the IPS patch format. Not only will the patch size be
smaller, but data and code that you did not change, but moved to another part
of the ROM, will not be fully included as copyrighted data combined with your
own changes.
-------------------------------------------------------------------------------
5b. NROM-128 to NROM-256 Conversion/Expansion - The Tutorial

 With all that said, let's explore how to go about expanding the Balloon Fight
NES ROM, specifically changing it from 16 KB of PRG-ROM to 32 KB of PRG-ROM.

Note: Hacking/changing/adding a mapper is not covered in this tutorial.

The programs and other files I use in this process are the following:
- A copy of the Balloon Fight ROM; you don't want to change your original!
- The WindHex32 hex editor (v.2005.4.20) by Bongo`.
- The FCEUXD emulator (v1.0a) by bbitmaster.

Optional programs (not required for the process in this tutorial, but they can
be used to provide visuals for further understanding):
- The Tile Layer Pro graphics editor (v1.1) by SnowBro (optional, but for
  visual purposes)
- The Tile Layer Pro 1.1 Unofficial Bug Fix Patch (v1.1) by Kejardon (optional,
  to apply to the Tile Layer Pro 1.1 utility with a patching program, such as
  Lunar IPS)
- Lunar IPS (v1.02) by FuSoYa (optional, for applying the Tile Layer Pro 1.1
  Unofficial Bug Fix Patch to the Tile Layer Pro 1.1 utility)

Text of steps using the listed optional programs will be enclosed in box shapes
for visual purposes and clarity. They are not necessary to do to complete the
expansion process successfully.


First, open your copy of the Balloon Fight ROM in the WindHex32 hex editor. At
the very top of the NES file, you should see the following bytes, starting at
0x0000:

4E 45 53 1A 01 01

The first 01, at ROM offset 0x0004, determines how many 16384 byte program ROM
pages there are.
The second 01, at ROM offset 0x0005, determines how many 8192 byte character
ROM pages there are.

Since we're adding a PRG-ROM page to change from NROM-128 to NROM-256, the byte
that we want to change is 0x0004, the first 01.

The reason why we are using WindHex32 to do this instead of the hex editor in
FCEUXD is because the emulator restricts you from modifying the header. With
the WindHex32 hex editor, we are able to modify the header of the file.

Highlight 0x0004, and change 01 to 02.
Under File, select "Save File...". Close WindHex32.

If you examine your Balloon Fight ROM file, the size still displays as 25 KB.
It appears as though the file isn't fully expanded yet, or the intended
additional space isn't fully detected and considered.

  +-------------------------------------------------------------------------+
  | OPTIONAL: Open your ROM file in the Tile Layer Pro graphics editor and  |
  |           try scrolling down as far as you can towards the bottom.      |
  |           The first offset displayed will be 0x5000 if you dragged the  |
  |           scrollbar all the way to the bottom, but by clicking the      |
  |           down arrow, the display will shift over and reveal one more   |
  |           tile, so now the first tile at the top-left displayed begins  |
  |           from 0x5010. This means that the end of the ROM is still      |
  |           considered as terminating at offset 0x600F, even though,      |
  |           after expanding the ROM file, the size should be larger than  |
  |           that. So, until this is fixed, we aren't even able to modify  |
  |           the bytes within the additional space. At least, not through  |
  |           this specific graphics editor, anyway.                        |
  +-------------------------------------------------------------------------+

So, next, open the ROM in FCEUXD. Instead of the game running properly and
displaying the title screen, you're met with a gray screen. Hey! What's the
deal? Not only did the file size not update, but now the game isn't even
showing up? This process isn't working at all!

Well, actually, it is! We just need to "fix" a few things to set the game back
up properly. Remember, now the $C000-$DFFF and $E000-$FFFF ranges in RAM are
different, which is where all the code originally functions. So, the "flow", if
you will, is currently broken in its new state as of right now. However, this
can be an easy fix, especially when you consider that no original chunks of
code bothered to use jump or load opcodes within the $8000-$BFFF range, which
means that we won't have to modify any code to account for the new range
applications, and we'll just have to move the appropriate ranges into their new
expected places for everything to come back together and flow again in its new
state!

First off, the CHR-ROM is now shifted down towards the end of the ROM file, and
the old CHR-ROM is now in place of where the PRG-ROM has been expanded into.

The newly created empty space consists of "FF" bytes, all the way down to and
including the very last byte, at 0xA00F in the ROM. For the game to acknowledge
the new end of the file, we need to change these "FF" bytes to basically
anything else.

So, let's start by first moving the CHR-ROM to its new place.
Highlight the range of 0x4010-0x600F (0x2000), and under Edit, select Copy.
Scroll down to and select ROM offset 0x8010, and under Edit, select Paste.
The range of 0x8010-0xA00F (0x2000) has now been updated to contain the
graphics originally within the old CHR-ROM range, meaning you have effectively
moved the bytes that draw the graphics, viewable in a graphics editor like
Tile Layer Pro, successfully!
Under File, select Save Rom.

If you examine your Balloon Fight ROM file now, the size has been updated to
41 KB. Yes! The file size is officially larger!

  +-------------------------------------------------------------------------+
  | OPTIONAL: Open your ROM file in the Tile Layer Pro graphics editor and  |
  |           try scrolling down as far as you can towards the bottom       |
  |           again. Unlike last time, the scrollbar can pass offset        |
  |           0x600F, and reach all the way down to 0xA00F, the new end of  |
  |           the ROM file! The offset displayed will be 0x9000 (or 0x9010  |
  |           after clicking the down arrow at least once), indicating the  |
  |           first byte that the first graphical tile starts from. If you  |
  |           click once above the scrollbar within the track, the bar will |
  |           move up exactly one page worth, displaying the first CHR-ROM  |
  |           page within the range of 0x8010-0x900F. This is the easiest   |
  |           way to display the correct range of a character ROM page in   |
  |           Tile Layer Pro for editing purposes, as dragging the          |
  |           scrollbar will place the first byte at 0x[xx]00 instead of    |
  |           0x[xx]10 by accounting for the NES ROM header. This can be    |
  |           avoided by not applying the Bug Fix Patch, but if the file    |
  |           does not have a header, then there are bytes that cannot be   |
  |           edited, according to the bug report.                          |
  +-------------------------------------------------------------------------+

However, we still need to fix the other ranges.

Let's revisit how the ROM is mapped to RAM in both setups, the previous one
being for NROM-128, and the current one being for NROM-256, to determine what
exactly we should be moving, and to where.

Balloon Fight - 24.0 KB (25 KB) - RAM (NROM-128):
$8000-$9FFF: 0x0010-0x200F ] Originally UNUSED.
$A000-$BFFF: 0x2010-0x400F ] Originally UNUSED.
$C000-$DFFF: 0x0010-0x200F ] USED.
$E000-$FFFF: 0x2010-0x400F ] USED.

Balloon Fight - 40.0 KB (41 KB) - RAM (NROM-256):
$8000-$9FFF: 0x0010-0x200F ] Essentially, new free space; still UNUSED.
$A000-$BFFF: 0x2010-0x400F ] Essentially, new free space; still UNUSED.
$C000-$DFFF: 0x4010-0x600F ] Where we need what is still in 0x0010-0x200F.
$E000-$FFFF: 0x6010-0x800F ] Where we need what is still in 0x2010-0x400F.

So, things seem to be backwards right now, don't they?
Basically, we need everything in the first program ROM page moved to the
second program ROM page.

With your expanded ROM still open in FCEUXD, and the hex editor still open,
scroll to and highlight the range of 0x0010-0x400F (0x4000), and under Edit,
select Copy.
Select ROM offset 0x4010, and under Edit, select Paste.
The range of 0x4010-0x800F (0x4000) now contains the data and code that makes
up the Balloon Fight game, which was originally loaded into RAM from
$C000-$FFFF to run the game, but once the ROM size changed, the bytes loading
to the $C000-$FFFF range in RAM were no longer the functional data and code
they once were.
Under File, select Save Rom.

Under the NES menu, if you select Reset or Power, the game now successfully
loads the title screen! Victory!

As an additional step, though an optional one (it's really best to do to
account for the empty space that you have created in the ROM within the range
of 0x0010-0x400F (0x4000)), you can clear out all of that space by overwriting
all the bytes with "FF" values.

Scroll to and highlight byte 0x0010. Begin to replace the bytes with "FF".
To speed up the process, once you have a range such as 0x0010-0x001F (0x10) or
0x0010-0x002F (0x20) replaced with all "FF" bytes, highlight the appropriate
range, and from the Edit menu, select Copy, followed by Paste (or hold CTRL+V
and conveniently speed up the process) to cover the entire range of
0x0010-0x400F (0x4000). Slow down the pasting as you approach 0x4010, as you
don't want to overwrite the CRITICAL data and code that you just finished
moving to get the game working again!
Once again, under File, select Save Rom.


 You have now successfully expanded the Balloon Fight ROM, doubling the program
ROM in size! How does it feel?

 As mentioned earlier, the potential advantages to making this change only
really come into play when one is able to make effective use of this additional
space.

 For myself, while designing my proof of concept Balloon Fight level hack, it
proved much easier to have lots of free space to work with while building the
levels from scratch, accounting for level headers, object data, enemy data,
level graphics, and platform collision/detection data, in order to put
everything together.

 It also provides lots of free space for additional subroutines to jump to for
additional game functions, or creating additional and/or expanded tables for
data groups such as individual level palettes, or even individual level
starting positions for both Players 1 and 2, if one's customized code is
designed to apply such enhancements and features.

 So, let's continue on with exploring more about the original Balloon Fight ROM
and the functions within it:

- How some variables are handled in RAM, and where they originate in ROM.
- The level header format, as well as how everything in a level is handled.
-------------------------------------------------------------------------------
 6. Balloon Fight RAM & ROM Addresses

 The following addresses/offsets are from my own findings through continuous
tests, and trial and error. Not everything in the entire ROM is covered - by a
long shot - but some essential game variables are explored.

RAM:
$0012 - Bytes left to load (ex. when loading tiles to draw for graphics)
$0019 - Game timer (if loops around on title screen, demo begins)
$001D - Address for loading pointer (level headers & palettes) (low byte)
$001E - Address for loading pointer (level headers & palettes) (high byte)
$001F - Address for graphics pointer (low byte)
$0020 - Address for graphics pointer (high byte)
$0023 - Address for left sides for platform detections (low byte)
$0024 - Address for left sides for platform detections (high byte)
$0025 - Address for right sides for platform detections (low byte)
$0026 - Address for right sides for platform detections (high byte)
$0027 - Address for top sides for platform detections (low byte)
$0028 - Address for top sides for platform detections (high byte)
$0029 - Address for bottom sides for platform detections (low byte)
$002A - Address for bottom sides for platform detections (high byte)
$003B - Current level header pointer to use (00 for Phase 1, 01 for Phase 2,
        etc.)
$003C - Current Phase count (displays at top of screen at beginning of Phase;
        does not increase for a Bonus Phase)
$003F - Game mode selected on title screen
              (00 = A  1 Player Game,
               01 = B  2 Player Game,
               02 = C  Balloon Trip)
$0040 - Number of players (00 = 1 player, 01 = 2 players)
$0041 - Player 1's lives
$0042 - Player 2's lives
$0049 - Rank in Balloon Trip (ones digit)
$004A - Rank in Balloon Trip (tens digit)
$0054 - Cloud X-coordinate for drawing
$0055 - Cloud Y-coordinate for drawing
$005A-$0079 - Palette
$0081-$0086 - Enemies' balloons status
              (00 = Flying, 01 = Downward descent, 02 = Sitting,
               03-06 = Balloon inflating status, FF = Collected bubble)
$0088 - Player 1's balloons
$0089 - Player 2's balloons
$008A-$008F - Enemies (00 = Falling, 01 = Sitting/umbrella,
                       02 = Balloon, 80 = Gone, FF = Doesn't exist)
$0091 - Player 1's horizontal position (Starting: 20)
$0092 - Player 2's horizontal position (Starting: D0)
$0093-$0098 - Enemies' horizontal positions
$0099 - Fish's horizontal position
$009A - Player 1's vertical position (Starting: B8)
$009B - Player 2's vertical position (Starting: B8)
$009C-$00A1 - Enemies' vertical positions
$00A2 - Fish's vertical position
$00BD - Player 1's invincibility (sprite graphic frozen)
$00BE - Player 2's invincibility (sprite graphic frozen)
$00BF - Player 1's invincibility flash
$00C0 - Player 2's invincibility flash
$00C8 - 00 = Regular Phase, 01 = Bonus Phase
$00CD - Number of platforms counter
$00CE - Unused
$00CF - Unused
$00F2 - Music
$0451 - Player 1 type (03 = 2 Balloons, 07 = 1 Balloon, 0B = Dead)
$0452 - Player 2 type (03 = 2 Balloons, 07 = 1 Balloon, 0B = Dead)
$0453-$0458 - Enemy types
$0558 - Bonus Phase intensity level
$0559 - x00 points per balloon in Bonus Phase
$055A - Rising speed for balloons in Bonus Phase
$055B - Bonus Phase super bonus (x0000 points; single digit)
$055C - Bonus Phase super bonus (0x000 points; single digit)
$05CD - Player 1 balloons collected in Bonus Phase
$05CE - Player 2 balloons collected in Bonus Phase

Music

$00F2 in RAM is the music! The possible music values differ by the bit set:
  00 - No music
  01 - Game over music
  02 - Phase ending music
  04 - Pausing tune/noise
  08 - Phase intro music
  10 - Bonus Phase bonus music (for collecting all 20 balloons)
  20 - Bonus Phase music (while playing the Bonus Phase)
  40 - Eaten by fish tune
  80 - Respawn from dying tune


ROM:
0x0004 - 01 - 1 PRG-ROM page
0x0005 - 01 - 1 CHR-ROM page
0x0006 - 00 - Mapper 0
0x1B2B - 2C - Cursor on title screen horizontal position (balloon)
0x1B37 - 8C - Cursor on title screen vertical position - A  1-Player Game
0x1B38 - 9C - Cursor on title screen vertical position - B  2-Player Game
0x1B39 - AC - Cursor on title screen vertical position - C  Balloon  Trip
0x3201 - 02 - Number of lives both players start out with
0x336C - 10 - Number of unique level header pointers
0x3370 - 04 - Level header pointer to begin reusing old Phase designs from
0x33A0 - B8 - Vertical starting position & spawning invincibility timer
0x33BE - 20 - Player 1's horizontal starting position
0x33BF - D0 - Player 2's horizontal starting position


Bonus Phase:

0x111D - 03 (300 points per balloon - Bonus Phase 01)
0x111E - 05 (500 points per balloon - Bonus Phase 02)
0x111F - 07 (700 points per balloon - Bonus Phase 03)
0x1120 - 07 (700 points per balloon - Bonus Phase 04)
0x1121 - 07 (700 points per balloon - All other Bonus Phases)

0x1122 - 80 (Rising speed for balloons - Bonus Phase 01)
0x1123 - 90 (Rising speed for balloons - Bonus Phase 02)
0x1124 - 98 (Rising speed for balloons - Bonus Phase 03)
0x1125 - A0 (Rising speed for balloons - Bonus Phase 04)
0x1126 - A8 (Rising speed for balloons - All other Bonus Phases)

0x1127 - 01 (Super bonus x0000 points; single digit - Bonus Phase 01)
0x1128 - 01 (Super bonus x0000 points; single digit - Bonus Phase 02)
0x1129 - 02 (Super bonus x0000 points; single digit - Bonus Phase 03)
0x112A - 02 (Super bonus x0000 points; single digit - Bonus Phase 04)
0x112B - 03 (Super bonus x0000 points; single digit - All other Bonus Phases)

0x112C - 00 (Super bonus 0x000 points; single digit - Bonus Phase 01)
0x112D - 05 (Super bonus 0x000 points; single digit - Bonus Phase 02)
0x112E - 00 (Super bonus 0x000 points; single digit - Bonus Phase 03)
0x112F - 05 (Super bonus 0x000 points; single digit - Bonus Phase 04)
0x1130 - 00 (Super bonus 0x000 points; single digit - All other Bonus Phases)

Example: 0x1127 - 01, 0x112C - 00 = 10000 points
         0x1128 - 01, 0x112D - 05 = 15000 points
         0x1129 - 02, 0x112E - 00 = 20000 points
         0x112A - 02, 0x112F - 05 = 25000 points
         0x112B - 03, 0x1130 - 00 = 30000 points


Title Screen:

  0x193C-0x193D (0x2) - 30 D9 (0x1940) - Pointer for title screen data

0x1940-0x1AD0 (0x191) - Title Screen
-------------------------------------------------------------------------------
 7. Level Header Format

 The levels, or Phases as referred to in the game, begin with the pointers that
tell the game where each level header begins from, with the level headers
containing multiple pointers that tell the game how to handle everything else
within, including graphics, objects, enemies, clouds, flippers, and the actual
physical placements of the platforms.

 Indeed, as strange as it may seem, physical and visual elements are handled
separately by this game. So, you could draw platforms somewhere, and have them
actually placed elsewhere. Essentially, you could be capable of having
invisible walls where graphics aren't displayed, and fake walls where graphics
are drawn, but not actually solid.

 The level header pointers are within the 0x1B3A-0x1B59 (0x20) range. The first
0x10 (in hex) bytes are for the lower byte/part of the RAM address, and the
second 0x10 (in hex) bytes are for the higher byte/part of the RAM address.

IMPORTANT SIDE NOTE: If you are working with an expanded ROM from sections 5a
and 5b, please remember that all of your ROM addresses are now 0x4000 (in hex)
bytes ahead from where they once were. So, for instance, in an expanded ROM,
the level header pointers are now within the range of 0x5B3A-0x5B59 (0x20).

 The level header pointers are as follows:

Phase 1:
0x1B3A: 4A
0x1B4A: DB
$DB4A in RAM, 0x1B5A in ROM

Phase 2:
0x1B3B: 59
0x1B4B: DB
$DB59 in RAM, 0x1B69 in ROM

Phase 3:
0x1B3C: F2
0x1B4C: DB
$DBF2 in RAM, 0x1C02 in ROM

Bonus Phase 1:
0x1B3D: 6C
0x1B4D: DB
$DB6C in RAM, 0x1B7C in ROM

Phase 4:
0x1B3E: 77
0x1B4E: DB
$DB77 in RAM, 0x1B87 in ROM

Phase 5:
0x1B3F: 88
0x1B4F: DB
$DB88 in RAM, 0x1B98 in ROM

Phase 6:
0x1B40: E1
0x1B50: DB
$DBE1 in RAM, 0x1BF1 in ROM

Bonus Phase 2:
0x1B41: 6C
0x1B51: DB
$DB6C in RAM, 0x1B7C in ROM

Phase 7:
0x1B42: 99
0x1B52: DB
$DB99 in RAM, 0x1BA9 in ROM

Phase 8:
0x1B43: 03
0x1B53: DC
$DC03 in RAM, 0x1C13 in ROM

Phase 9:
0x1B44: CA
0x1B54: DB
$DBCA in RAM, 0x1BDA in ROM

Bonus Phase 3:
0x1B45: 6C
0x1B55: DB
$DB6C in RAM, 0x1B7C in ROM

Phase 10:
0x1B46: AD
0x1B56: DB
$DBAD in RAM, 0x1BBD in ROM

Phase 11:
0x1B47: 17
0x1B57: DC
$DC17 in RAM, 0x1C27 in ROM

Phase 12:
0x1B48: E1
0x1B58: DB
$DBE1 in RAM, 0x1BF1 in ROM

Bonus Phase 4:
0x1B49: 6C
0x1B59: DB
$DB6C in RAM, 0x1B7C in ROM

 The following code, located at 0x12B0 in the ROM, checks to see what the next
level to look for is, and then stores the pointers into RAM as a reference
address to load the next necessary information from the correct level header:

$D2A0:A4 3B     LDY $3B = #$00               ; Check current level build to use
$D2A2:B9 2A DB  LDA $DB2A,Y @ $DB2A = #$4A   ; Level header address (low byte)
$D2A5:85 1D     STA $1D = #$4A               ; Store in RAM
$D2A7:B9 3A DB  LDA $DB3A,Y @ $DB3A = #$DB   ; Level header address (high byte)
$D2AA:85 1E     STA $1E = #$D9               ; Store in RAM

 Once Phase 12 has been completed, followed by Bonus Phase 4, the game reuses
the level data starting from Phase 4, though the game will appropriately label
the current level as Phase 13.

 Next, let's check the actual level headers:

Bonus Phase:
0x1B7C-0x1B86 (0xB)
CA DC 00 00 FF FF B0 DF 00 9A DE

Phase 1:
0x1B5A-0x1B68 (0xF)
2B DC 39 DD 00 00 10 06 FF FF 96 DF 02 7A DE

Phase 2:
0x1B69-0x1B7B (0x13)
2B DC 39 DD 4B DD 00 00 18 0C 04 0E FF FF A0 DF 04 86 DE

Phase 3:
0x1C02-0x1C12 (0x11)
2B DC 01 DE 00 00 04 08 16 10 FF FF 07 E0 09 2E DF

Phase 4:
0x1B87-0x1B97 (0x11)
2B DC 5E DD 00 00 08 06 18 0A FF FF B1 DF 06 9E DE

Phase 5:
0x1B98-0x1BA8 (0x11)
2B DC 7D DD 00 00 04 06 12 08 FF FF C1 DF 07 BA DE

Phase 6:
0x1BF1-0x1C01 (0x11)
2B DC DB DD 00 00 0E 06 0C 14 FF FF F7 DF 06 12 DF

Phase 7:
0x1BA9-0x1BBC (0x14)
2B DC A3 DD 00 00 06 06 14 10 FF 0F 0D 01 FF D4 DF 09 DA DE

Phase 8:
0x1C13-0x1C26 (0x14)
2B DC 32 DE 00 00 04 10 18 10 FF 0E 06 01 FF 17 E0 07 56 DF

Phase 9:
0x1BDA-0x1BF0 (0x17)
2B DC 5E DD 00 00 10 06 1A 0C FF 08 08 01 18 04 01 FF B1 DF 06 9E DE

Phase 10:
0x1BBD-0x1BD9 (0x1D)
2B DC CE DD 00 00 04 06 10 0E FF 08 0E 03 0D 09 03 12 08 03 17 0D 03 FF E7 DF
03 02 DF

Phase 11:
0x1C27-0x1C3A (0x14)
2B DC 5B DE 00 00 04 08 0E 10 FF 10 07 01 FF 2A E0 07 76 DF

Phase 12:
0x1BF1-0x1C01 (0x11)
2B DC DB DD 00 00 0E 06 0C 14 FF FF F7 DF 06 12 DF

 Using Phase 9's level header as an example, here is the format broken down:

2B DC 5E DD 00 00 10 06 1A 0C FF 08 08 01 18 04 01 FF B1 DF 06 9E DE

2B DC - Main Phase graphics - the shared graphics between all of the Phases,
        but different for the Bonus Phase (as there aren't two platforms at the
        very bottom, or the water that separates them). This saves space by
        reusing the data for common graphics, but the next 2 bytes account for
        the other graphics in each Phase.
5E DD - Unique stage graphics - the remaining graphics to draw for a Phase.
00 00 - A separator of sorts between pointers for graphics and cloud locations.
10 06 - 2 bytes per cloud. The X-coordinate is first (left to right), and the
        Y-coordinate is second (up to down). In the original game, the Bonus
        Phase has no clouds, and each Phase has either 1 cloud or 2 clouds.
        If more are added, one or more clouds may flash, but the lightning may
        shoot out from an improper place, specifically where the cloud isn't.
        You must be careful when setting each coordinate for a cloud. Some
        axis placements will cause parts of a cloud to use the first quarter of
        the object palette instead of the last quarter (green and red instead
        of gray and white).
1A 0C - Second cloud. See above for more information.
   FF - Separator following the clouds, leading into flipper locations.
        If a level has no flippers, there are two "FF" bytes together.
08 08 - Location of first flipper. The X-coordinate is first (left to right),
        and the Y-coordinate is second (up to down).
   01 - Flipper type/starting position. In the original game, Phase 10 uses the
        most flippers in a single Phase, 4 flippers.
        00 = Top-left to down-right   \
        01 = Up-down                  |
        02 = Bottom-left to top-right /
        03 = Flat                     -
18 04 - Location of additional flipper.
   01 - Flipper type/starting position.
   FF - End of flipper locations and types.
B1 DF - Enemy data
   06 - Number of platforms, minus one, to detect. For example, there are 7
        platforms in Phase 9, but 00 counts as one.
        The highest number of platforms used in a single Phase in the original
        game is 10 (0A in hex), with this byte set to 09, in Phases 3 and 7.
        More should be possible, though this theory has not been tested yet.
9E DE - Platform collision/detection.

 With more clarity on how the level header system is set up and how it works,
let's dig deeper into the various components of a given Phase that are direct
results from this makeup.
-------------------------------------------------------------------------------
 8. Platform Collision/Detection

 The third-to-last byte in the level header tells the game how many platforms
there are in the Phase, so that it knows how many bytes representing each side
there are to load.

 The bytes that represent the left and right sides of the platforms are
X-coordinates, and the values of their possible placements increase from left
to right, using the horizontal axis.

 The bytes that represent the top and bottom sides of the platforms are
Y-coordinates, and the values of their possible placements increase from up
to down, using the vertical axis.

 Using Phase 3's platform detection as an example, here is the format broken
down:

0x1F3E-0x1F65 (0x28)

 Platform #  00 01 02 03 04 05 06 07 08 09
  Left Side  10 C8 50 C8 88 40 70 D0 88 48
 Right Side  38 FF 60 E0 98 58 90 D8 90 50
   Top Side  CF CF 37 37 5F 87 B7 3C 64 8C
Bottom Side  E0 E0 40 40 68 90 C0 60 80 A8

 The "Platform #" row is only included for visual convenience, and the
incrementing numbers are not actually bytes in the ROM.

 The third-to-last byte in Phase 3's level header is 09 (in hex), and means
that Phase 3 has 10 (in decimal) platforms, counting 00 as the first platform.

 So, the first platform, which is the bottom-left platform which Player 1
starts on, has a left side 10 pixels in, a right side that extends to 38 pixels
in, a top side resting CF pixels down from the top, and a bottom side resting
E0 pixels from the top.

 Do note that the first two platforms are the same for every Phase excluding
the Bonus Phases, which is where the shared graphics come in, except for Phase
2, with both platforms covering an additional 4 pixels each towards the middle
opening into the water. Why they do this, who knows?


 Let's examine the detections that make up the platforms in all of the Phases:


Bonus Phase:
0x1EAA-0x1EAD (0x4)

 Platform #  00
  Left Side  10
 Right Side  FF
   Top Side  DF
Bottom Side  EC


Phase 1:
0x1E8A-0x1E95 (0xC)

 Platform #  00 01 02
  Left Side  10 C8 48
 Right Side  38 FF B8
   Top Side  CF CF 8F
Bottom Side  E0 E0 98


Phase 2:
0x1E96-0x1EA9 (0x14)

 Platform #  00 01 02 03 04
  Left Side  10 C4 48 B8 28
 Right Side  3C FF B8 E8 58
   Top Side  CF CF 8F 4F 57
Bottom Side  E0 E0 98 58 60


Phase 3:
0x1F3E-0x1F65 (0x28)

 Platform #  00 01 02 03 04 05 06 07 08 09
  Left Side  10 C8 50 C8 88 40 70 D0 88 48
 Right Side  38 FF 60 E0 98 58 90 D8 90 50
   Top Side  CF CF 37 37 5F 87 B7 3C 64 8C
Bottom Side  E0 E0 40 40 68 90 C0 60 80 A8


Phase 4:
0x1EAE-0x1EC9 (0x1C)

 Platform #  00 01 02 03 04 05 06
  Left Side  10 C8 80 30 B8 60 90
 Right Side  38 FF 98 48 D0 78 A8
   Top Side  CF CF 5F 87 8F 97 B7
Bottom Side  E0 E0 68 90 98 A0 C0


Phase 5:
0x1ECA-0x1EE9 (0x20)

 Platform #  00 01 02 03 04 05 06 07
  Left Side  10 C8 58 68 C8 28 50 98
 Right Side  38 FF 70 78 D0 30 68 B0
   Top Side  CF CF 2F 57 4F 67 A7 A7
Bottom Side  E0 E0 38 6C 6C 7C B0 B0


Phase 6:
0x1F22-0x1F3D (0x1C)

 Platform #  00 01 02 03 04 05 06
  Left Side  10 C8 40 A0 28 D0 60
 Right Side  38 FF 60 C0 30 D8 90
   Top Side  CF CF 3F 3F 67 67 97
Bottom Side  E0 E0 48 48 88 88 A0


Phase 7:
0x1EEA-0x1F11 (0x28)

 Platform #  00 01 02 03 04 05 06 07 08 09
  Left Side  10 C8 12 DA BA 9A 5A 3A 1A 7A
 Right Side  38 FF 1E E6 C6 A6 66 46 26 96
   Top Side  CF CF 37 37 4F 5F 7F 8F 9F AF
Bottom Side  E0 E0 40 40 58 68 88 98 A8 B8


Phase 8:
0x1F66-0x1F85 (0x20)

 Platform #  00 01 02 03 04 05 06 07
  Left Side  10 C8 20 C0 40 A8 60 98
 Right Side  38 FF 40 E0 60 C8 68 A0
   Top Side  CF CF 37 37 67 67 97 97
Bottom Side  E0 E0 40 40 70 70 B0 B0


Phase 9:
0x1EAE-0x1EC9 (0x1C)

 Platform #  00 01 02 03 04 05 06
  Left Side  10 C8 80 30 B8 60 90
 Right Side  38 FF 98 48 D0 78 A8
   Top Side  CF CF 5F 87 8F 97 B7
Bottom Side  E0 E0 68 90 98 A0 C0


Phase 10:
0x1F12-0x1F21 (0x10)

 Platform #  00 01 02 03
  Left Side  10 C8 52 92
 Right Side  38 FF 66 A6
   Top Side  CF CF AF AF
Bottom Side  E0 E0 B8 B8


Phase 11:
0x1F86-0x1FA5 (0x20)

 Platform #  00 01 02 03 04 05 06 07
  Left Side  10 C8 20 40 60 A0 C0 E0
 Right Side  38 FF 30 50 70 B0 D0 F0
   Top Side  CF CF 97 7F 67 67 7F 97
Bottom Side  E0 E0 A0 88 70 70 88 A0


Phase 12:
0x1F22-0x1F3D (0x1C)

 Platform #  00 01 02 03 04 05 06
  Left Side  10 C8 40 A0 28 D0 60
 Right Side  38 FF 60 C0 30 D8 90
   Top Side  CF CF 3F 3F 67 67 97
Bottom Side  E0 E0 48 48 88 88 A0


 Next, those platforms want their presence to be known to the world of the
living, so it's important to draw the tiles needed for them to be displayed.
-------------------------------------------------------------------------------
 9. Graphics

 Here is a basic breakdown of how the graphics are drawn to the screen:

 [PPU Address] [Number of Bytes] [Bytes] [Repeat as Many Times as Needed] [00]

 A similar format is used in Super Mario Bros. 3 (NES) for the text displayed
during the game ending sequence with the world maps once the curtains go up.
The desired PPU Address to begin drawing tiles to is chosen, followed by the
number of tiles (in hex) to draw, and then repeat until a "00" byte outside of
drawing (tile #$00 could potentially be drawn for graphics).

 In FCEUXD, by using the Name Table Viewer, you can hover your mouse cursor
over any given tile to see the Tile ID, X/Y-coordinates, and the PPU Address
for a tile or range of tiles.

 The graphics displayed for the Balloon Fight Phases use Name Table #0, PPU
Memory $2000-$23BF (0x3C0), and Attribute Table #0, PPU Memory $23C0-$23FF
(0x40).


 As an example, let's look at the shared graphics for every Phase (excluding
the Bonus Phase), located in the range of 0x1C3B-0x1CD9 (0x9F) in the ROM.

 Here are the first 3 bytes:

23 40 88

 This means the starting PPU Address is $2340, and that there are 88 (in hex,
136 in decimal) bytes to draw. That's quite a lot! Let's look at them by row.
Each row has 20 (in hex, 32 in decimal) bytes.

PPU Memory $2340-$235F
{3938393839383933} {24242424242424242424242424242424} {3038393839383938}
  Left platform          Open area above water          Right platform

PPU Memory $2360-$237F
{3C3B3C3B3C3B3C3D} {58595A5B58595A5B58595A5B58595A5B} {3A3B3C3B3C3B3C3B}
  Left platform               Top of water              Right platform

PPU Memory $2380-$239F
{6061626360616263} {5C5D5E5F5C5D5E5F5C5D5E5F5C5D5E5F} {6061626360616263}
 Water under left                Water                 Water under right

PPU Memory $23A0-$23BF
{5C5D5E5F5C5D5E5F} {5C5D5E5F5C5D5E5F5C5D5E5F5C5D5E5F} {5C5D5E5F5C5D5E5F}
 Water under left                Water                 Water under right


 The following bytes continue into PPU Memory $23C0-$23C7 (0x8). The Attribute
Table determines which quarter of the object palette each tile section uses.
These 8 bytes in particular set the proper colours for the top part of the
screen where the players' scores and lives are displayed.

40 50 50 50 50 90 A0 A0

 That ends the 136 values stored from that group. Next, the format repeats with
another group, all to be stored at the end of Attribute Table #0 to set the
appropriate colours used for the bottom part of the screen.

23 F0 10

 Starting at PPU Address $23F0, there are 10 (in hex, 16 in decimal) bytes.

00 00 A0 A0 A0 A0 00 00 0A 0A 0A 0A 0A 0A 0A 0A

 Finally, outside of drawing, we end with a 00 byte.

00


 For more information on Attribute Tables, please refer to other documentation
included in this download, or available online, or at your local library,
written by other helpful and informative people.

 Though, quite honestly, you shouldn't really have to change or add anything
to affect it, as additional consideration should only be necessary if your
level designs are more customized and advanced in comparison to those in the
original game.

 The original game has unused image and sprite graphical tiles which can be
used to increase detail on custom title screens and for level backgrounds.
-------------------------------------------------------------------------------
10. Enemy Data

 The enemy data format is considerably simple and straight forward.

 A maximum of 6 enemies per Phase is allowed.

 If there is not at least 1 enemy in a Phase's data set, the game will assume
that it is a Bonus Phase, and even with a Phase's level data loaded, balloons
will rise up from the ground and water.


 Using Phase 11's enemy data as an example, here is the format broken down:

0x203A-0x204C (0x13)
06 20 80 04 40 68 05 60 50 06 A0 50 06 C0 68 05 E0 80 04

      06 - Number of enemies
20 80 04 - X:20, Y:80, Type 04
40 68 05 - X:40, Y:68, Type 05
60 50 06 - X:60, Y:50, Type 06
A0 50 06 - X:A0, Y:50, Type 06
C0 68 05 - X:C0, Y:68, Type 05
E0 80 04 - X:E0, Y:80, Type 04

 The very first byte tells the game how many enemies there are. If this byte is
00, the game will assume that it is a Bonus Phase. In RAM, the enemy variables
allow up to 6 enemies in each Phase.

 Following that, each group of 3 bytes represents 1 enemy. The first byte is
the X-coordinate, the second byte is the Y-coordinate, and the third byte is
the enemy type.

 Type 04 is the pink balloon enemy, the slowest and least aware.
 Type 05 is the green balloon enemy, a little more aware than the pink.
 Type 06 is the beige balloon enemy, the fastest and most aware.

 Using other numbers spawns enemies with mixed up colours and controls. It is
probably best not to use them.

 No "00" byte terminator at the end of an enemy data set is required.


 Here are the enemy data sets for all of the Phases:


Bonus Phase:
0x1FC0 (0x1)
00

      00 - No enemies


Phase 1:
0x1FA6-0x1FAF (0xA)
03 58 78 04 78 78 04 98 78 04

      03 - 3 enemies
58 78 04 - X:58, Y:78, Type 04
78 78 04 - X:78, Y:78, Type 04
98 78 04 - X:98, Y:78, Type 04


Phase 2:
0x1FB0-0x1FBF (0x10)
05 C8 38 05 38 40 05 58 78 04 78 78 04 98 78 04

      05 - 5 enemies
C8 38 05 - X:C8, Y:38, Type 05
38 40 05 - X:38, Y:40, Type 05
58 78 04 - X:58, Y:78, Type 04
78 78 04 - X:78, Y:78, Type 04
98 78 04 - X:98, Y:78, Type 04


Phase 3:
0x2017-0x2026 (0x10)
05 50 20 06 C8 20 06 84 48 05 44 70 05 78 A0 04

      05 - 5 enemies
50 20 06 - X:50, Y:20, Type 06
C8 20 06 - X:C8, Y:20, Type 06
84 48 05 - X:84, Y:48, Type 05
44 70 05 - X:44, Y:70, Type 05
78 A0 04 - X:78, Y:A0, Type 04


Phase 4:
0x1FC1-0x1FD0 (0x10)
05 94 A0 06 84 48 05 34 70 04 64 80 04 BC 78 04

      05 - 5 enemies
94 A0 06 - X:94, Y:A0, Type 06
84 48 05 - X:84, Y:48, Type 05
34 70 04 - X:34, Y:70, Type 04
64 80 04 - X:64, Y:80, Type 04
BC 78 04 - X:BC, Y:78, Type 04


Phase 5:
0x1FD1-0x1FE3 (0x13)
06 5C 18 06 24 50 05 64 40 05 C4 38 05 54 90 04 9C 90 04

      06 - 6 enemies
5C 18 06 - X:5C, Y:18, Type 06
24 50 05 - X:24, Y:50, Type 05
64 40 05 - X:64, Y:40, Type 05
C4 38 05 - X:C4, Y:38, Type 05
54 90 04 - X:54, Y:90, Type 04
9C 90 04 - X:9C, Y:90, Type 04


Phase 6:
0x2007-0x2016 (0x10)
05 50 28 06 A8 28 06 24 50 06 CC 50 06 70 80 04

      05 - 5 enemies
50 28 06 - X:50, Y:28, Type 06
A8 28 06 - X:A8, Y:28, Type 06
24 50 06 - X:24, Y:50, Type 06
CC 50 06 - X:CC, Y:50, Type 06
70 80 04 - X:70, Y:80, Type 04


Phase 7:
0x1FE4-0x1FF6 (0x13)
06 10 20 06 D8 20 06 B8 38 05 98 48 05 58 68 05 38 78 04

      06 - 6 enemies
10 20 06 - X:10, Y:20, Type 06
D8 20 06 - X:D8, Y:20, Type 06
B8 38 05 - X:B8, Y:38, Type 05
98 48 05 - X:98, Y:48, Type 05
58 68 05 - X:58, Y:68, Type 05
38 78 04 - X:38, Y:78, Type 04


Phase 8:
0x2027-0x2039 (0x13)
06 28 20 06 C8 20 06 48 50 05 B0 50 05 5C 80 04 94 80 04

      06 - 6 enemies
28 20 06 - X:28, Y:20, Type 06
C8 20 06 - X:C8, Y:20, Type 06
48 50 05 - X:48, Y:50, Type 05
B0 50 05 - X:B0, Y:50, Type 05
5C 80 04 - X:5C, Y:80, Type 04
94 80 04 - X:94, Y:80, Type 04


Phase 9:
0x1FC1-0x1FD0 (0x10)
05 94 A0 06 84 48 05 34 70 04 64 80 04 BC 78 04

      05 - 5 enemies
94 A0 06 - X:94, Y:A0, Type 06
84 48 05 - X:84, Y:48, Type 05
34 70 04 - X:34, Y:70, Type 04
64 80 04 - X:64, Y:80, Type 04
BC 78 04 - X:BC, Y:78, Type 04


Phase 10:
0x1FF7-0x2006 (0x10)
05 54 98 05 94 98 05 6C 39 06 94 31 06 BC 59 06

      05 - 5 enemies
54 98 05 - X:54, Y:98, Type 05
94 98 05 - X:94, Y:98, Type 05
6C 39 06 - X:6C, Y:39, Type 06
94 31 06 - X:94, Y:31, Type 06
BC 59 06 - X:BC, Y:59, Type 06


Phase 11:
0x203A-0x204C (0x13)
06 20 80 04 40 68 05 60 50 06 A0 50 06 C0 68 05 E0 80 04

      06 - 6 enemies
20 80 04 - X:20, Y:80, Type 04
40 68 05 - X:40, Y:68, Type 05
60 50 06 - X:60, Y:50, Type 06
A0 50 06 - X:A0, Y:50, Type 06
C0 68 05 - X:C0, Y:68, Type 05
E0 80 04 - X:E0, Y:80, Type 04


Phase 12:
0x2007-0x2016 (0x10)
05 50 28 06 A8 28 06 24 50 06 CC 50 06 70 80 04

      05 - 5 enemies
50 28 06 - X:50, Y:28, Type 06
A8 28 06 - X:A8, Y:28, Type 06
24 50 06 - X:24, Y:50, Type 06
CC 50 06 - X:CC, Y:50, Type 06
70 80 04 - X:70, Y:80, Type 04
-------------------------------------------------------------------------------
11. Object Data

 Basically, object data in this game is a combination of both the platform
collision/detection/solidity, and the visual graphics, which are handled
separately, unlike other games which generally have groups of bytes
representing TSA (Tile Square Assembly), a term coined by hackers throughout
the years meaning tiles that make up larger blocks drawn to the screen.

 Please refer to sections 8 and 9 for information on platform detection and
graphics.
-------------------------------------------------------------------------------
12. Palette Data

 The palette is stored at the $005A-$0079 region in RAM to be transferred over
to the PPU.

 Here are the offsets for the palettes and other related data in the ROM:


0x113B-0x113D (0x3) - Palette write to $3F00 (0x10 in hex bytes)
3F 00 10

0x113E-0x114D (0x10) - Palette for points screen after a Bonus Phase
0F 30 30 30 0F 30 27 15 0F 30 02 21 0F 16 16 16


0x1447-0x1449 (0x3) - Palette write to $3F00 (0x20 in hex bytes)
3F 00 20

0x144A-0x1469 (0x20) - Palette for Phases
0F 2A 09 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B


0x146A-0x146D (0x4) - 1/4 object palette change for Phases 01-03
0F 2A 09 07

0x146E-0x1471 (0x4) - 1/4 object palette change for Phases 04-06
0F 26 06 07

0x1472-0x1475 (0x4) - 1/4 object palette change for Phases 07-09
0F 1B 0C 07

0x1476-0x1479 (0x4) - 1/4 object palette change for Phases 10-12
0F 2C 01 06


0x147A-0x1483 (0xA) - Pointers for Bonus Phase palettes
74 7C 84 84 84 D4 D4 D4 D4 D4

0x147A - 74, 0x147F - D4 - $D474 - 0x1484 - Bonus Phase 01
0x147B - 7C, 0x1480 - D4 - $D47C - 0x148C - Bonus Phase 02
0x147C - 84, 0x1481 - D4 - $D484 - 0x1494 - Bonus Phase 03
0x147D - 84, 0x1482 - D4 - $D484 - 0x1494 - Bonus Phase 04
0x147E - 84, 0x1483 - D4 - $D484 - 0x1494 - All other Bonus Phases

0x1484-0x1487 (0x4) - 1/4 object palette change for Bonus Phase 01
0F 02 08 06

0x1488-0x148B (0x4) - 3/4 sprite palette change for Bonus Phase 01
0F 2B 30 12

0x148C-0x148F (0x4) - 1/4 object palette change for Bonus Phase 02
0F 07 0A 19

0x1490-0x1493 (0x4) - 3/4 sprite palette change for Bonus Phase 02
0F 26 30 2B

0x1494-0x1497 (0x4) - 1/4 object palette change for Bonus Phase 03, 04, etc.
0F 07 0C 1C

0x1498-0x149B (0x4) - 3/4 sprite palette change for Bonus Phase 03, 04, etc.
0F 15 30 26


0x1940-0x1942 (0x3) - Palette write to $3F00 (0x4 in hex bytes)
3F 00 04

0x1943-0x1946 (0x4) - Palette for title screen image/logo, graphics and text
0F 30 27 2A

0x1947-0x1949 (0x3) - Palette write to $3F18 (0x4 in hex bytes)
3F 18 04

0x194A-0x194D (0x4) - Palette for title screen balloon cursor sprite
0F 16 30 21
-------------------------------------------------------------------------------
13. Fish

 The fish is not fully documented yet, but here is what has been found so far.

 The following RAM addresses are related to the fish:

$0099 - Fish's horizontal position
$00A2 - Fish's vertical position

 The following ROM addresses are related to the fish:

0x0660 - B1 - Possible right max value that the fish's horizontal position can
              become
0x0664 - 40 - Possible left max value that the fish's horizontal position can
              become
0x06E9 - 40 - Left max horizontal position within which the fish can attack
0x06ED - B1 - Right max horizontal position within which the fish can attack
0x34D0 - 40 - Fish's starting horizontal position

 By changing 0x06E9 and 0x06ED, the fish will be able to attack at a horizontal
position where there could be a player or enemy, but only if 0x0660 and 0x0664
are changed as well to match, or else the continuously cycling value of the
fish's horizontal position ($0099 in RAM) will not be able to BECOME the values
of an increased range without the modification of both pairs of variables in
either direction.

 (In progress. More to come. Sorry.)
-------------------------------------------------------------------------------
14. Tips - Building Your Levels From Scratch

 To make a level from nothing, especially while having to work directly in a
hex editor, might feel like an overwhelming process, but we just have to take
it one step at a time. Ask yourself, what do we need? Well, we need a level
header, and we need to know all of the ROM offsets, set as the appropriate
RAM addresses, to point to for retrieving all of the appropriate data to build
the level; this includes graphics, clouds, flippers, enemy data, and the
platform detection data for solid objects.

 Some unknown factors can include which order to do/set certain variables, like
between drawing the graphics, and setting the detections for the platforms.

 Initially, I would visualize the level that I wanted to make in my head, and
then I would virtually do everything except the custom Phase graphics. So, I
would set the platform detection before I would add the tiles to draw and
represent them.

 However, a potentially better strategy, especially for beginner hackers, is to
draw the graphics for your intended level first, and then once you have the
correct number of platforms required to set, you can set your appropriate
platform detections from trial and error.

 For each level that I'm currently editing, I modify the pointers for the very
first level header, at 0x1B3A and 0x1B4A (or 0x5B3A and 0x5B4A in an expanded
ROM) accordingly. This way, I can make changes to test, and before saving them,
reset and reload the first level to see if the settings are correct, or require
further trial and error to get just right.

 For the variable in the level header setting the number of platforms, try to
always start by setting it to 01, and set only the detection data for the
bottom two platforms that are in every Phase:

10 C8 38 FF CF CF E0 E0

 Once you have all your graphics set up, you'll know how many platforms there
are for sure in your level, so you'll know how many you have to account for,
and then you can set everything accordingly, and hopefully much more easily.

 For placing enemies, adjust the coordinates by increments or decrements of 01
each time, making sure that enemies do not float through platforms or flippers,
or drop down slightly before reaching a solid ground.

 For matching up visuals for platforms with their intended detections, test out
moving your player along and into each side of every platform, wherever
possible (excluding the bottom two main platforms, since as long as you use the
same settings as the Phases in the original game, no adjustments should be
required for them specifically). If your player moves into graphics from the
left or right, either adjust your detection or graphics accordingly.
-------------------------------------------------------------------------------
15. Examples of Custom Code

 Here are some examples of code changes that you can implement for your very
own Balloon Fight hack!
-------------------------------------------------------------------------------
a. Disable Game Demo

Original code:
--------------
$DACE (0x1ADE)

$DACE:A5 19     LDA $19
$DAD0:F0 1F     BEQ $DAF1

Hex editor view:
----------------
0x1ADE-0x1AE1 (0x4)
A5 19 F0 1F

What to change:
---------------
0x1AE0-0x1AE1 (0x2)
EA EA

This will disable the title screen from loading the demo.
-------------------------------------------------------------------------------
b. Disable Fish

Original code:
--------------
$C627 (0x0637)

$C627:C5 99     CMP $99
$C629:F0 04     BEQ $C62F

$C64B (0x065B)

$C64B:E6 99     INC $99
$C64D:A5 99     LDA $99

$C653 (0x0663)

$C653:A9 40     LDA #$40
$C655:85 99     STA $99

Hex editor view:
----------------
0x0637-0x063A (0x4)
C5 99 F0 04

0x065B-0x065E (0x4)
E6 99 A5 99

0x0663-0x0666 (0x4)
A9 40 85 99

What to change:
---------------
0x0637-0x063A (0x4)
EA EA EA EA

0x065B-0x065E (0x4)
EA EA EA EA

0x0663-0x0666 (0x4)
EA EA EA EA

This will prevent the fish from appearing at all. Float near the water. Feel it
on the balloon fighter's behind! Feels cool and refreshing, doesn't it?
-------------------------------------------------------------------------------
c. Custom Palette Code

 This hack requires an expanded ROM in order to have enough free space to fit
in all the custom palette data (unless you work magic that I haven't bothered
to try). It can be customized to suit your own personal needs.

 Please refer to section 5b for directions on how to expand your Balloon Fight
ROM.

$B000-$B022
0x3010-0x3032 (0x23) - New Phase 1 palette
3F 00 20
0F 2A 09 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B023-$B045
0x3033-0x3055 (0x23) - New Phase 2 palette
3F 00 20
0F 2A 09 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B046-$B068
0x3056-0x3078 (0x23) - New Phase 3 palette
3F 00 20
0F 2A 09 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B069-$B08B
0x3079-0x309B (0x23) - New Bonus Phase 1 palette
3F 00 20
0F 02 08 06 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 2B 30 12 0F 17 11 2B

$B08C-$B0AE
0x309C-0x30BE (0x23) - New Phase 4 palette
3F 00 20
0F 26 06 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B0AF-$B0D1
0x30BF-0x30E1 (0x23) - New Phase 5 palette
3F 00 20
0F 26 06 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B0D2-$B0F4
0x30E2-0x3104 (0x23) - New Phase 6 palette
3F 00 20
0F 26 06 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B0F5-$B117
0x3105-0x3127 (0x23) - New Bonus Phase 2 palette
3F 00 20
0F 07 0A 19 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 26 30 2B 0F 17 11 2B

$B118-$B13A
0x3128-0x314A (0x23) - New Phase 7 palette
3F 00 20
0F 1B 0C 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B13B-$B15D
0x314B-0x316D (0x23) - New Phase 8 palette
3F 00 20
0F 1B 0C 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B15E-$B180
0x316E-0x3190 (0x23) - New Phase 9 palette
3F 00 20
0F 1B 0C 07 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B181-$B1A3
0x3191-0x31B3 (0x23) - New Bonus Phase 3 palette
3F 00 20
0F 07 0C 1C 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 15 30 26 0F 17 11 2B

$B1A4-$B1C6
0x31B4-0x31D6 (0x23) - New Phase 10 palette
3F 00 20
0F 2C 01 06 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B1C7-$B1E9
0x31D7-0x31F9 (0x23) - New Phase 11 palette
3F 00 20
0F 2C 01 06 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B1EA-$B20C
0x31FA-0x321C (0x23) - New Phase 12 palette
3F 00 20
0F 2C 01 06 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 17 11 35 0F 17 11 2B

$B20D-$B22F
0x321D-0x323F (0x23) - New Bonus Phase 4 palette
3F 00 20
0F 07 0C 1C 0F 30 27 15 0F 30 02 21 0F 30 00 10
0F 16 12 37 0F 12 16 37 0F 15 30 26 0F 17 11 2B

$B230-$B24F
0x3240-0x325F (0x20) - Palette pointers/reference addresses
                       0x3240-0x324F (0x10) are low bytes
                       0x3250-0x325F (0x10) are high bytes
                       Ex. 0x3240 - 00, 0x3250 - B0 = $B000 (0x3010)
00 23 46 69 8C AF D2 F5 18 3B 5E 81 A4 C7 EA 0D
B0 B0 B0 B0 B0 B0 B0 B0 B1 B1 B1 B1 B1 B1 B1 B2

$B250-$B274
0x3260-0x3284 (0x25)

$B250:A9 69     LDA #$69      ; First, set the Balloon Trip palette
$B252:85 1D     STA $1D       ; It'll be ready for if the player selects
$B254:A9 B0     LDA #$B0      ; Balloon Trip, which uses the same palette as
$B256:85 1E     STA $1E       ; Bonus Phase 1 (palette is at $B069, or 0x3079)
$B258:A5 3F     LDA $3F       ; Check the game mode selected
$B25A:C9 02     CMP #$02      ; If it's Balloon Trip
$B25C:F0 0C     BEQ $B26A     ; Then keep the $B069 palette reference address
$B25E:A6 3B     LDX $3B       ; If not, then check which level is being loaded
$B260:BD 30 B2  LDA $B230,X   ; Retrieve the low byte first
$B263:85 1D     STA $1D       ; Store it
$B265:BD 40 B2  LDA $B240,X   ; Retrieve the high byte next
$B268:85 1E     STA $1E       ; Store that sucker
$B26A:A0 22     LDY #$22      ; Ready to retrieve all the palette data now
$B26C:B1 1D     LDA ($1D),Y   ; Find correct palette from reference address to
$B26E:99 57 00  STA $0057,Y   ; Store palette values
$B271:88        DEY           ; Decrement Y register to
$B272:10 F8     BPL $B26C     ; Capture all bytes before you
$B274:60        RTS           ; Return to $D3F0 for other stuff

$D3ED-$D436
0x53FD-0x5446 (0x4A)

$D3ED:20 50 B2  JSR $B250     ; First things first; jump to $B250
$D3F0:A5 C8     LDA $C8       ; Check if regular Phase or Bonus Phase
$D3F2:F0 40     BEQ $D434     ; Get out if a regular Phase - jump to $D434
$D3F4:AE 58 05  LDX $0558     ; Check Bonus Phase intensity level to
$D3F7:BD 6A D4  LDA $D46A,X   ; Determine palette for floating balloons
$D3FA:85 1D     STA $1D       ; Store low byte for new reference pointer
$D3FC:BD 6F D4  LDA $D46F,X   ; As well as the
$D3FF:85 1E     STA $1E       ; High byte
$D401:A2 03     LDX #$03      ; There will be 4 values to change in the
$D403:A0 03     LDY #$03      ; Third quarter of the sprite palette
$D405:B1 1D     LDA ($1D),Y   ; Read the value
$D407:95 72     STA $72,X     ; Store the value for the balloon colour change
$D409:88        DEY           ; Do it
$D40A:CA        DEX           ; Again
$D40B:10 F8     BPL $D405     ; For all 4 values
$D40D:EA        NOP           ; Make all the rest of the code "No Operation"
$D40E:EA        NOP           ; So that nothing happens
$D40F:EA        NOP           ; From possibly any other original code that
$D410:EA        NOP           ; Points to a spot in this code
$D411:EA        NOP           ; Although it shouldn't be the case
$D412:EA        NOP           ; But better safe than sorry
$D413:EA        NOP           ; So, see you later
$D414:EA        NOP
$D415:EA        NOP
$D416:EA        NOP
$D417:EA        NOP
$D418:EA        NOP
$D419:EA        NOP
$D41A:EA        NOP
$D41B:EA        NOP
$D41C:EA        NOP
$D41D:EA        NOP
$D41E:EA        NOP
$D41F:EA        NOP
$D420:EA        NOP
$D421:EA        NOP
$D422:EA        NOP
$D423:EA        NOP
$D424:EA        NOP
$D425:EA        NOP
$D426:EA        NOP
$D427:EA        NOP
$D428:EA        NOP
$D429:EA        NOP
$D42A:EA        NOP
$D42B:EA        NOP
$D42C:EA        NOP
$D42D:EA        NOP
$D42E:EA        NOP
$D42F:EA        NOP
$D430:EA        NOP
$D431:EA        NOP
$D432:EA        NOP
$D433:EA        NOP           ; Oh, hello again
$D434:4C 2D C1  JMP $C12D     ; Oh, okay, bye again... or "byte" again

0x547A-0x547E (0x5) - Changed from original Bonus Phase palette changes in the
78 80 88 88 88        original game, which changed the first quarter of the
                      image palette and the third quarter of the enemy palette,
                      instead of just the third quarter of the enemy palette as
                      we're doing in this modified code, as the only factor we
                      need to consider anymore is the floating balloons, as the
                      rest of the palette is set beforehand from our full,
                      individual level palettes.
-------------------------------------------------------------------------------
16. Acknowledgements, Credits & Thank You Section

     bbitmaster - For the always extremely useful FCEUXD emulator.
         Bongo` - For the awesome WindHex32 hex editor.
           byuu - For the very sweet alternative patching program for the BPS
                  format.
         FuSoYa - For the fun and easy to use Lunar IPS patching program.
       Nintendo - For the addictively entertaining Balloon Fight game.
 Romhacking.net - For hosting and informative purposes over the years.
        SnowBro - For the amazing Tile Layer Pro graphics editor.
 Vicious Poetry - For document reviewing & testing.

 The following people have provided helpful information, suggestions, and/or
advice, so thank you to:

  Disch - Finally, I had the privilege to communicate directly with this well-
          known, talented individual. He provided some possible ASM hacking
          ideas for Balloon Fight, as well as some personal perspectives and
          approaches. Hopefully I'll be capable of following through with some
          of these awesome ideas and be able to provide potential code sources
          for others to refer to.
dougeff - A very talented ROM hacker and homebrewer who I have been able to
          become great friends with and communicate with on a regular basis,
          bouncing ideas around with one another and providing great support
          and encouragement.
Jeville - Encouraged fish detection and Balloon Trip, and other related data.
-------------------------------------------------------------------------------
17. Other Potential Areas of Consideration/What's to Come

 Here are other things that could possibly be explored and documented in later
updates of this documentation:

- More thorough exploration of specific data and code in the original ROM.
- More descriptive, step-by-step tutorials for usage of recommended utilities.
- Sound and music data.
- Provided custom code.
- More fish related data.
- Balloon Trip related data.

 If you are able to provide any additional information to what is already here,
have any additional suggestions of what can be added, or any methods of how to
better explain what is already here, please feel free to contact me. Please
refer to the "Contacts" section for methods of contact, or feel free to post in
the topic, "Balloon Fight (NES) Hacking", on the Romhacking.net forum at the
following link:

http://www.romhacking.net/forum/index.php/topic,20232.0.html

 Whether you have a question about your own Balloon Fight hacking project, any
information that you would like to contribute, or just want to join the
discussion in general, please stop by!

 Any information that is contributed to this document will be properly credited
in the "Acknowledgements, Credits & Thank You Section". Thank you.
-------------------------------------------------------------------------------
18. Change Log

v1.0 - Original document released August 5, 2015.

v1.1 - Section 2 labeling mismatch: "Hacking Tools" in the Table of Contents
       and "What You Will Need" in the actual section. Now it's fixed to
       include both in both locations.
     - Removed improper comparison between Bonus Phase music and Wrecking Crew
       golden hammer music. Why I thought that they were the same at the moment
       that I wrote that, I have no idea.
     - Fixed mix-up of "horizontal" and "vertical" for player and enemy
       positions in RAM and ROM addresses list. Oops. I apologize for any
       inconveniences this error has already caused.
     - Added sections "13. Fish", "15. Examples of Custom Code", and "17. Other
       Potential Areas of Consideration/What's to Come".
     - Found some fish related data, including horizontal and vertical position
       in RAM.
     - Added 3 examples of custom code:
        - a. Disable Game Demo
        - b. Disable Fish
        - c. Custom Palette Code
       (Boy, this document is already much longer than it already was. A split
        might be necessary.)
-------------------------------------------------------------------------------
19. Contacts

------------
Quick Curly:

Board 2
http://acmlm.no-ip.org/board/profile.php?id=1121

Jul
http://jul.rustedlogic.net/profile.php?id=1111

Kafuka
http://board.kafuka.org/profile.php?id=111

Romhacking.net
http://www.romhacking.net/community/1051/
http://www.romhacking.net/forum/index.php?action=profile;u=3816

YouTube
http://www.youtube.com/user/Qu1ckCur1y

Email: quickcurly[at]yahoo[dot]ca
------------

------------
Intruder X:

CD Baby
http://www.cdbaby.com/Artist/IntruderX

MySpace
http://www.myspace.com/intruderxmusic

YouTube
http://www.youtube.com/user/intruderxmusic

  GRENADE STUDIOS - Musical instruction/instrument repair/recording studio.
  Email: livegrenade[at]sympatico[dot]ca
------------
